package br.ufrj.ppgi.infovis.forms;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.mt4j.AbstractMTApplication;
import org.mt4j.components.TransformSpace;
import org.mt4j.components.visibleComponents.widgets.MTListCell;
import org.mt4j.input.inputProcessors.IGestureEventListener;
import org.mt4j.input.inputProcessors.MTGestureEvent;
import org.mt4j.input.inputProcessors.componentProcessors.tapProcessor.TapEvent;
import org.mt4j.input.inputProcessors.componentProcessors.tapProcessor.TapProcessor;
import org.mt4j.util.MTColor;
import org.mt4j.util.font.IFont;

import br.ufrj.ppgi.infovis.mtgraph.GraphScene;
import br.ufrj.ppgi.infovis.mtgraph.GraphToolBar;

import processing.core.PApplet;

/**
 * <p>
 * Class implementing the AbstractOverlayDefaultList. Represents the overlay
 * view for loading a new MindMap. Shows a list of all available .mindMap files.
 * Selecting a list entry will load the selected .mindMap file.
 * </p>
 * @see map.mindMapper.view.AbstractOverlayDefaultList
 * 
 */
public class OverlayListLoadGraph extends AbstractOverlayDefaultList {
    /* *** List cell constants *** */
    /** The list cell padding */
    private static final int      LIST_CELL_PADDING                = 2;
    /** The list cell fill color */
    private static final MTColor  LIST_CELL_FILL_COLOR             = MTColor.GREY;
    /** The list cell fill color on pressing the cell item */
    private static final MTColor  LIST_CELL_FILL_PRESSED_COLOR     = MTColor.GREY;
    /** The list cell font color */
    private static final MTColor  LIST_CELL_FONT_COLOR             = MTColor.WHITE;

    /** The list cell height in percent of the list height */
    private static final float    LIST_CELL_HEIGHT_TO_LIST_PERCENT = 0.20f;

    /** The maximum number of lines in the list cell text field */
    private static final int      LIST_CELL_MAX_LINE_NUMBER        = 2;

    /** The cell text field width offset */
    private static final float    CELL_LABEL_WIDTH_OFFSET          = 8f;

    /* *** Application *** */
    /** The multitouch application instance */
    private AbstractMTApplication mtApplication;
    /** The currently active mindMapScene */
    private GraphScene          GraphScene;
    
    /** The list of mindMap files in the mindMapCollection */
    private List<File>               mindMapCollectionFiles;

    /** The list of mindMap names in the mindMapCollection */
    private List<String>             mindMapFileNames;                                     // files

    private String fullPath;

    /**
     * Constructor. Instantiates a new OverlayListLoadMindMap.
     * 
     * @param pApplet
     *            the application instance
     * @param mindMapScene
     *            the mindMapScene the overlay is added to
     * @param x
     *            the x position of the overlay
     * @param y
     *            the y position of the overlay
     * @param width
     *            the width of the overlay
     * @param height
     *            the height of the overlay
     * @param headlineFont
     *            the font for the headline
     * @param listFontDefault
     *            the font for the list content
     * @param listFontSmaller
     *            the smaller font for the list content
     */
    public OverlayListLoadGraph(PApplet pApplet, GraphScene graphScene, float x, float y, float width, float height, IFont headlineFont,
            IFont listFontDefault, IFont listFontSmaller) {
        super(pApplet, x, y, width, height, headlineFont, listFontDefault,
                listFontSmaller);
        // Set app reference, mindMapScene reference and font
        this.mtApplication = (AbstractMTApplication) pApplet;
        this.GraphScene = graphScene;
        // Initialize
        initialize();
    }

    /* ********Getters & Setters******** */

    /**
     * Returns the mindMapScene of the OverlayListLoadMindMap
     * 
     * @return the mindMapScene
     */
    public GraphScene getMindMapScene() {
        return this.GraphScene;
    }

    /* **********Object methods********** */

    /**
     * Initializes the OverlayListLoadMindMap.
     * 
     */
    private void initialize() {
        // Set headline text
        setHeadlineText();
        // Add list cells
        addListCells();
    }

    /**
     * Sets the OverlayListLoadMindMap headline text.
     * 
     */
    private void setHeadlineText() {
        // Set headline text
        getHeadlineTextField().setText("Importar");
    }

    /**
     * Adds list cells to the overlay list as well as list cells behaviour.
     * 
     * @return true, if adding the list cells was successful
     */
    private boolean addListCells() {
        if (this.GraphScene != null
                && this.getListContentDefaultFont() != null
                && this.getListContentSmallerFont() != null) {

            // Update files list
        	this.updateMindMapFilesList();
            // Get files list
            List<File> fileList = getMindMapCollectionFiles();
            // Get list width
            float listWidth = getOverlayList().getWidthXY(TransformSpace.GLOBAL);
            float listHeight = getOverlayList().getHeightXY(TransformSpace.GLOBAL);
         // Create a new list cell for every .mindMap save file
            for (File file : fileList) {
                String fileNameWOExtension;
                String fileName = file.getName();
                if (fileName.endsWith(GlobalDefs.FILE_EXTENSION)) {
                    fileNameWOExtension = fileName.substring(0, fileName.length() - GlobalDefs.FILE_EXTENSION.length());
                } else {
                    // We assume there are only .mindMap files in the
                    // list
                    // because
                    // mindMapCollection.updateMindMapFilesList() makes
                    // sure of that
                    fileNameWOExtension = fileName;
                }

                // Add cell for every save file
                getOverlayList()
                        .addListElement(
                                this.createListCell(
                                        fileNameWOExtension,
                                        this.getListContentDefaultFont(),
                                        this.getListContentSmallerFont(),
                                        listWidth
                                                - (LIST_CELL_PADDING * 2),
                                        (listHeight * LIST_CELL_HEIGHT_TO_LIST_PERCENT)
                                                - (LIST_CELL_PADDING * 2),
                                        LIST_CELL_FILL_COLOR,
                                        LIST_CELL_FILL_PRESSED_COLOR,
                                        LIST_CELL_FONT_COLOR));
            }
            return true;
        }
        return false;
    }

    /**
     * Creates a new list cell with the given label text.
     * 
     * @param label
     *            the text for the cell
     * @param fontBig
     *            the bigger font for the cell
     * @param fontSmall
     *            the smaller font for the cell
     * @param cellWidth
     *            the cell width
     * @param cellHeight
     *            the cell height
     * @param cellFillColor
     *            the cell fill color
     * @param cellPressedFillColor
     *            the cell color when pressed
     * @param cellFontColor
     *            the cell font color
     * @return the created cell
     */
    private MTListCell createListCell(final String label, IFont fontBig, IFont fontSmall, float cellWidth, float cellHeight,
            final MTColor cellFillColor, final MTColor cellPressedFillColor, final MTColor cellFontColor) {
        final MTListCell cell = new MTListCell(this.mtApplication, cellWidth, cellHeight);
        cell.setFillColor(cellFillColor);
        MTTextFieldVarLinesFontSwitch listLabel = new MTTextFieldVarLinesFontSwitch(
                this.mtApplication, 0, 0, cellWidth - CELL_LABEL_WIDTH_OFFSET,
                cellHeight, LIST_CELL_MAX_LINE_NUMBER, fontBig, fontSmall);
        listLabel.setNoFill(true);
        listLabel.setNoStroke(true);
        listLabel.setText(label);
        listLabel.setFontColor(cellFontColor);
        // Set cell name the label, also (required for list selection later)
        cell.setName(label);
        cell.addChild(listLabel);
        listLabel.setPositionRelativeToParent(cell.getCenterPointLocal());
        cell.unregisterAllInputProcessors();
        cell.registerInputProcessor(new TapProcessor(this.mtApplication, 15));
        cell.addGestureListener(TapProcessor.class,
                new IGestureEventListener() {
                    @SuppressWarnings("synthetic-access")
                    @Override
                    public boolean processGestureEvent(MTGestureEvent ge) {
                        TapEvent te = (TapEvent) ge;
                        switch (te.getTapID()) {
                            case TapEvent.TAP_DOWN:
                                cell.setFillColor(cellPressedFillColor);
                                break;
                            case TapEvent.TAP_UP:
                                cell.setFillColor(cellFillColor);
                                break;
                            case TapEvent.TAPPED:
                                cell.setFillColor(cellFillColor);
                                // Load selected mindMap
                                // Find file by name (we unfortunately have get
                                // no list index from the MTList/MTListCells)
                                File mindMapToLoadFile = getFileByName(cell.getName());
                                if (mindMapToLoadFile != null) {
                                	loadMindMap(mindMapToLoadFile);
                                } else {
                                	System.out.println("Error: selected file not found!");
                                }
                                // Close overlay
                                //OverlayListLoadGraph.this.destroy();
                                break;
                        }
                        return false;
                    }
                });
        return cell;
    }

    /* ********Overridden methods******** */

    /**
     * Overriden method destroy() from AbstractShape. Adds behaviour required on
     * destruction of the OverlayListLoadMindMap instance.
     * 
     * @see org.mt4j.components.visibleComponents.shapes.AbstractShape#destroy()
     */
    @Override
    public void destroy() {
        super.destroy();
        // Set in null in mindMap
        if (this.GraphScene != null) {
            // Set loadMindMapOverlay null
/*AKI            
        	this.mindMapScene.setLoadMindMapOverlay(null);*/
        }
    }
    
    public ArrayList<File> getMindMapCollectionFiles() {
        return (ArrayList<File>) this.mindMapCollectionFiles;
    }
    protected void setMindMapCollectionFiles(List<File> mindMapCollectionFiles) {
       this.mindMapCollectionFiles = mindMapCollectionFiles;
    }

    public boolean loadMindMap(File file) {
        if (file != null) {
        	fullPath = file.getAbsolutePath();
            if (fullPath == null) {
                return false;
            }
    		//TOOLBAR		
    		GraphToolBar gtb = new GraphToolBar(this.GraphScene);
    		gtb.Import(fullPath, false);
            return true;
        } else {
            System.out.println("Error: invalid file");
        }
        return false;
    }

    /**
     * Updates the current file list of the MindMapCollection.
     * 
     */
    public void updateMindMapFilesList() {
        File folder = new File(GlobalDefs.FILE_PATH);//"src/br/ufrj/ppgi/infovis/data/");
        File[] listOfFiles = folder.listFiles();
        String fileName;
        // clear / (re-) initialize arrays
        this.mindMapCollectionFiles = new ArrayList<File>();
        this.mindMapFileNames = new ArrayList<String>();

        if (listOfFiles != null) {
            // Get paths and names for all .mindMap files in the directory
            for (int i = 0; i < listOfFiles.length; i++) {
                if (listOfFiles[i].isFile()) {
                    fileName = listOfFiles[i].getName();

                    // TODO: Change to interface filenamefilter ??
                    // Check if files are .mindMap files, add to lists
                    if (fileName.endsWith(GlobalDefs.FILE_EXTENSION)) {
                        this.mindMapFileNames.add(fileName);
                        this.mindMapCollectionFiles.add(listOfFiles[i]);
                    }
                }
            }
        }
    }
    

    public File getFileByName(String name) {
        if (name != null) {
            // Update file list
            this.updateMindMapFilesList();
            List<File> fileList = this.mindMapCollectionFiles;
            for (File file : fileList) {
                if (file.getName().equals(name + GlobalDefs.FILE_EXTENSION)) {
                    return file;
                }
            }
            return null;
        }
        return null;
    }
}
